Unity 基础 之 简单实现鼠标点击(手机触屏)非 UI 处监听双击事件/长按事件的功能(内附判断点击在UI上还是非UI上的方法)

您所在的位置:网站首页 unity windows触屏 Unity 基础 之 简单实现鼠标点击(手机触屏)非 UI 处监听双击事件/长按事件的功能(内附判断点击在UI上还是非UI上的方法)

Unity 基础 之 简单实现鼠标点击(手机触屏)非 UI 处监听双击事件/长按事件的功能(内附判断点击在UI上还是非UI上的方法)

2024-06-26 03:53| 来源: 网络整理| 查看: 265

 

 

Unity 基础 之 简单实现鼠标点击(手机触屏)非 UI 处监听双击事件/长按事件的功能(内附判断点击在UI上还是非UI上的方法)

 

目录

Unity 基础 之 简单实现鼠标点击(手机触屏)非 UI 处监听双击事件/长按事件的功能(内附判断点击在UI上还是非UI上的方法)

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键代码

附录(备注):

 

一、简单介绍

Unity中的一些基础知识点。

本节介绍,在 Unity 中,简单实现当鼠标或者手机手机触屏在不是 UI 元素上面的双击事件和长按事件的功能,便于后期使用,有不对,欢迎指正。

 

二、实现原理

1、使用封装的 IsPointerOverUIObject() 判断是否点击在非 UI 处

2、监听 Event.current.isMouse && Event.current.type == EventType.MouseDown 是鼠标,且是鼠标按下事件(对应手机上的手指触屏)

3、监听 Event.current.clickCount == 2 双击事件触发

4、Update 通过时间差,监听长按事件触发

 

三、注意事项

1、因为使用到 EventSystem,所以场景中一定要有对应的 EventSystem 组件(既可以是UI的必备组件EventSystem )

2、移动端Touch Input Module输入模式下不正常,弃用了监听 EventSystem.current.IsPointerOverGameObject() == false (PC )或者 EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId) == false ( 移动端 ) 非UI处 这个方式

 

四、效果预览

 

五、实现步骤

1、打开Unity,新建空工程

 

2、在场景中,搭建UI,用来区分有UI处和 非 UI处

 

3、在工程中新建脚本,DoubleClickLongPressNonUIWrapper 实现点击非UI处双击/长按的功能,MonoSingleton 单例,TestDoubleClickLongPressNonUIWrapper 测试 DoubleClickLongPressNonUIWrapper   功能

 

4、把 TestDoubleClickLongPressNonUIWrapper 脚本挂载到场景中

 

5、运行场景(或打包到移动设备上),效果如上

 

六、关键代码

1、DoubleClickLongPressNonUIWrapper

using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace XANTools { /// /// 非 UI处的双击和长按事件封装 /// 注意,场景中一定要有 EventSystem 组件 /// public class DoubleClickLongPressNonUIWrapper : MonoSingleton { /// /// 初始化监听非UI处长按和双击事件 /// public void Init(Action doubleClickListener, Action longPressListener) { doubleClickAction = doubleClickListener; longPressAction = longPressListener; } // Update is called once per frame void Update() { // 长按监听 LongPress(); } /// /// 监听点击非UI处的,双击和长按触发条件监听 /// void OnGUI() { // 鼠标按下才监控 if (Input.GetMouseButtonDown(0)) { // 點擊非UI,是鼠标按下 if (IsPointerOverUIObject() == false && Event.current.isMouse && Event.current.type == EventType.MouseDown) { // 监听长按事件 isMouseDown = true; longPressTime = Time.time; // 双击事件 if (Event.current.clickCount == 2) { if (doubleClickAction != null) { doubleClickAction(); } //Debug.Log("双击NonUI"); } } } else if (Event.current.type == EventType.MouseUp) { //Debug.Log("MouseUp"); isMouseDown = false; } } /// /// 长按监听 /// 1、触发一次,需要松开再次长按才能触发下一次 /// void LongPress() { if (isMouseDown == true) { if (Time.time - longPressTime > longPressIntervalTime) { // 触发长按 if (longPressAction != null) { longPressAction(); } longPressTime = Time.time; isMouseDown = false; //Debug.Log("长按NonUI"); } } } #region 判断是否点击在UI上 /// /// Cast a ray to test if Input.mousePosition is over any UI object in EventSystem.current. This is a replacement /// for IsPointerOverGameObject() which does not work on Android in 4.6.0f3 /// private bool IsPointerOverUIObject() { if (EventSystem.current == null) return false; // Referencing this code for GraphicRaycaster https://gist.github.com/stramit/ead7ca1f432f3c0f181f // the ray cast appears to require only eventData.position. PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current); eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y); List results = new List(); EventSystem.current.RaycastAll(eventDataCurrentPosition, results); return results.Count > 0; } /// /// Cast a ray to test if screenPosition is over any UI object in canvas. This is a replacement /// for IsPointerOverGameObject() which does not work on Android in 4.6.0f3 /// private bool IsPointerOverUIObject(Canvas canvas, Vector2 screenPosition) { if (EventSystem.current == null) return false; // Referencing this code for GraphicRaycaster https://gist.github.com/stramit/ead7ca1f432f3c0f181f // the ray cast appears to require only eventData.position. PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current); eventDataCurrentPosition.position = screenPosition; GraphicRaycaster uiRaycaster = canvas.gameObject.GetComponent(); List results = new List(); uiRaycaster.Raycast(eventDataCurrentPosition, results); return results.Count > 0; } #endregion 判断是否点击在UI上 // 双击事件 Action doubleClickAction; // 长按事件 Action longPressAction; // 是否按下 private bool isMouseDown = false; // 长按触发时长 private float longPressIntervalTime = 0.6f; // 长按计时器 private float longPressTime = 0f; } }

 

2、TestDoubleClickLongPressNonUIWrapper

using System.Collections; using System.Collections.Generic; using UnityEngine; using XANTools; public class TestDoubleClickLongPressNonUIWrapper : MonoBehaviour { // Start is called before the first frame update void Start() { DoubleClickLongPressNonUIWrapper.Instance.Init(()=> { Debug.Log("双击NonUI"); }, () => { Debug.Log("长按NonUI"); }); } }

 

3、MonoSingleton

using UnityEngine; public abstract class MonoSingleton : MonoBehaviour where T : MonoBehaviour { private static T instance = null; private static readonly object locker = new object(); private static bool bAppQuitting; public static T Instance { get { if (bAppQuitting) { instance = null; return instance; } lock (locker) { if (instance == null) { // 保证场景中只有一个 单例 T[] managers = Object.FindObjectsOfType(typeof(T)) as T[]; if (managers.Length != 0) { if (managers.Length == 1) { instance = managers[0]; instance.gameObject.name = typeof(T).Name; return instance; } else { Debug.LogError("Class " + typeof(T).Name + " exists multiple times in violation of singleton pattern. Destroying all copies"); foreach (T manager in managers) { Destroy(manager.gameObject); } } } var singleton = new GameObject(); instance = singleton.AddComponent(); singleton.name = "(singleton)" + typeof(T); singleton.hideFlags = HideFlags.None; DontDestroyOnLoad(singleton); } instance.hideFlags = HideFlags.None; return instance; } } } protected virtual void Awake() { bAppQuitting = false; } protected virtual void OnDestroy() { bAppQuitting = true; } }

 

附录(备注):

1、DoubleClickLongPressNonUIWrapper(这个脚本在移动端Touch Input Module输入模式下不正常,弃用了)

using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; namespace XANTools { /// /// 非 UI处的双击和长按事件封装 /// 注意,场景中一定要有 EventSystem 组件 /// public class DoubleClickLongPressNonUIWrapper : MonoSingleton { /// /// 初始化监听非UI处长按和双击事件 /// public void Init(Action doubleClickListener, Action longPressListener) { doubleClickAction = doubleClickListener; longPressAction = longPressListener; } // Update is called once per frame void Update() { // 长按监听 LongPress(); } /// /// 监听点击非UI处的,双击和长按触发条件监听 /// void OnGUI() { // 鼠标按下才监控 if (Input.GetMouseButtonDown(0)) { #if UNITY_EDITOR // 點擊非UI,是鼠标按下 if (EventSystem.current.IsPointerOverGameObject() == false && Event.current.isMouse && Event.current.type == EventType.MouseDown) #elif ((UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR) // 移动端 if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId) == false && Event.current.isMouse && Event.current.type == EventType.MouseDown) #endif { #if UNITY_EDITOR Debug.Log("EventSystem.current.IsPointerOverGameObject() ="+ EventSystem.current.IsPointerOverGameObject()); #elif ((UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR) Debug.Log("EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId) = " + EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)); #endif // 监听长按事件 isMouseDown = true; longPressTime = Time.time; // 双击事件 if (Event.current.clickCount == 2) { if (doubleClickAction != null) { doubleClickAction(); } //Debug.Log("双击NonUI"); } } } else if (Event.current.type == EventType.MouseUp) { Debug.Log("MouseUp"); isMouseDown = false; } } /// /// 长按监听 /// 1、触发一次,需要松开再次长按才能触发下一次 /// void LongPress() { if (isMouseDown == true) { if (Time.time - longPressTime > longPressIntervalTime) { // 触发长按 if (longPressAction != null) { longPressAction(); } longPressTime = Time.time; isMouseDown = false; //Debug.Log("长按NonUI"); } } } // 双击事件 Action doubleClickAction; // 长按事件 Action longPressAction; // 是否按下 private bool isMouseDown = false; // 长按触发时长 private float longPressIntervalTime = 0.6f; // 长按计时器 private float longPressTime = 0f; } }

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3